﻿
namespace Pibby.Core.Web
{
    using System;
    using System.ComponentModel;
    using System.Net;

    /// <summary>
	/// Surpisingly, used to download stuff from the intertoobs
	/// </summary>
    public class WebDownloadingService : DisposableObject, IDownloadingService
    {
        #region Attributes

        private WebClient _webClient;

        #endregion

        #region Events

		public event EventHandler<ProgressEventArgs> DownloadProgressChanged;
		public event EventHandler<DownloadCompleteEventArgs> DownloadFileCompleted;
		public event EventHandler<DownloadCompleteEventArgs> DownloadDataCompleted;

        #endregion
		
        #region Constructors

        public WebDownloadingService()
        {
        }

		~WebDownloadingService()
		{
			Dispose(false);
		}
		
        #endregion

        #region Properties

		public bool Async
		{
			get;
			set;
		}

		public bool IsBusy
		{
			get { return this.Client.IsBusy; }
		}

			
		private WebClient Client
		{
			get
			{
				if (this._webClient == null)
				{
					this._webClient = new WebClient();
					this._webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
					this._webClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
					this._webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webClient_DownloadDataCompleted);
					
					//if (this.NetworkSettings.UseAuthentication)
					//{
					//    NetworkCredential credentials = new NetworkCredential(this.NetworkSettings.UserName, this.NetworkSettings.Password, this.NetworkSettings.Domain); // CredentialCache.DefaultNetworkCredentials; // .DefaultCredentials;
					//    this.Client.Credentials = credentials;
					//    this.Client.Proxy = this.Proxy;
					//    this.Client.Proxy.Credentials = credentials;
					//}
				}
				
				return this._webClient;
			}
        }

        #endregion

        #region Methods

		protected override void  ReleaseManagedResources()
		{
			base.ReleaseManagedResources();

			if (this.Disposed)
				return;

			if (this._webClient != null)
			{
				this._webClient.DownloadProgressChanged -= webClient_DownloadProgressChanged;
				this._webClient.DownloadFileCompleted -= webClient_DownloadFileCompleted;
				this._webClient.DownloadDataCompleted -= webClient_DownloadDataCompleted;

				this._webClient.Dispose();
				this._webClient = null;
			}
		}

        public void Download(string source, string target)
		{
			if (this.Disposed)
				throw new ObjectDisposedException("WebDownloadingService");

			if (this.Async)
				this.Client.DownloadFileAsync(new Uri (source), target);
			else
				this.Client.DownloadFile(new Uri(source), target);
		}

		public string DownloadAsString(string source)
		{
			if (this.Disposed)
				throw new ObjectDisposedException("WebDownloadingService");

			Contract.EnsureIsNotNullOrEmpty (source, "Url has not been set");

			string content = string.Empty;

			if (this.Async)
				this.Client.DownloadStringAsync(new Uri (source));
			else
				content = this.Client.DownloadString(new Uri (source));

			return content;
        }

		public byte[] DownloadData(string source)
		{
			if (this.Disposed)
				throw new ObjectDisposedException("WebDownloadingService");

			Contract.EnsureIsNotNullOrEmpty(source, "Url has not been set");

			byte[] data = null;

			if (this.Async)
				this.Client.DownloadDataAsync (new Uri(source));
			else
				data = this.Client.DownloadData (new Uri(source));

			return data;
		}

        #endregion

        #region Event Handlers

		private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
			EventHandler<DownloadCompleteEventArgs> complete = this.DownloadFileCompleted;

			if (complete != null)
				complete(this, new DownloadCompleteEventArgs(e.Error));
        }

		private void webClient_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
        {
			EventHandler<ProgressEventArgs> progress = this.DownloadProgressChanged;

			if (progress != null)
				progress(this, new ProgressEventArgs(e.ProgressPercentage));
		}

		private void webClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
		{
			EventHandler<DownloadCompleteEventArgs> complete = this.DownloadDataCompleted;

			if (complete != null)
				complete(this, new DownloadCompleteEventArgs(e.Error));
		}

		#endregion

	}
}
